/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
		build: grunt.file.readJSON('build.json'),
		project: grunt.file.readJSON('project.json'),
    // Task configuration.

    uglify: {
      options: {
        mangle: false
      },
      vips: {
        expand: true,
        src: ['<%= branch_src %>/js/**/*.js'],
				dest: '<%= branch_dest %>/js/',
				rename: function (dest, src) {
					// 去掉branch目录名，并生成对应的子目录
					var path_pattern = /\/js\/(.*)/,
							filepath = src.match(path_pattern)[1];
					return dest + filepath;
				}
      }
    },
    cssmin: {
      vips: {
        expand: true,
        flatten: false,
        src: ['<%= branch_src %>/css/**/*.css'],
				dest: '<%= branch_dest %>/css/',
				rename: function (dest, src) {
					// 去掉branch目录名，并生成对应的子目录
					var path_pattern = /\/css\/(.*)/,
							filepath = src.match(path_pattern)[1];
					return dest + filepath;
				}
      }
    },
    processCss: {
      options: {
        imgDomain: '<%= build.imgDomain %>',
        version: '2.0'
      },
			vips: '<%= cssmin.vips.dest %>'
    },
    shell: {
			push: {
				command: 'svn commit -m "' + grunt.option('m') + '" ' + (grunt.option('branch') || '<%= branch_dest %>'),
				options: {
					stdout: true,
					callback: function (err, stdout, stderr, cb) {
						grunt.log.ok(grunt.config('shell.push.command'));
						ChangeLog.generate(stdout, err);
						cb();
					}
				}
			},
			update: {
				command: 'svn update ' + (grunt.option('branch') || '<%= branch_dest %>'),
				options: {
					stderr: true,
					callback: function (err, stdout, stderr, cb) {
						grunt.log.ok(grunt.config('shell.update.command'));
						if (err) {
							grunt.fatal(err);
						}
						cb();
					}
				}
			},
			st: {
				command: 'svn st ' + (grunt.option('branch') || '<%= branch_dest %>'),
				options: {
					stderr: true,
					callback: function (err, stdout, stderr, cb) {
						grunt.log.ok(grunt.config('shell.st.command'));
						if (stdout) {
							// 保存结果到最后 finish 输出
							var st_data = grunt.config('st_data') || {'msg': []};
							st_data.msg.push(stdout);
							grunt.config('st_data', st_data);
						}
						cb();
					}
				}
			}
    }
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-shell');
  //grunt.loadNpmTasks('grunt-contrib-concat');
  //grunt.loadNpmTasks('grunt-contrib-nodeunit');
  //grunt.loadNpmTasks('grunt-contrib-jshint');
  //grunt.loadNpmTasks('grunt-contrib-watch');

	function init_project(project) {
		// 检查配置
		['name', 'description', 'branches'].map(function (name) {
			if (!project.hasOwnProperty(name)) {
				grunt.log.error(project);
				grunt.fatal('缺失配置：' + name);
			}
		});
		if (project.name.trim() == '') {
			grunt.fatal('请指定要构建的项目名');
		}
		// 设置到内部，共享使用
		grunt.config('_project', project);
	}

  // Default task.
  grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);

	// build task
	grunt.registerTask('build', function(project) {
		var project = project ? grunt.config(project) : grunt.config('project');
		init_project(project);

		// tasklist to be run
		// 保存所有相关的分支名
		var branches = {
					dev: [],
					test: []
				},
				static_branches = project.branches['static'] || {},
				tpl_branches = project.branches['tpl'] || {},
				branch_src = branch_dest = tpl_src = tpl_dest = '';

		// 对应静态资源分支的处理
		for (branch_src in static_branches) {
			grunt.log.debug('Building ' + branch_src);

			branch_dest = static_branches[branch_src];
			grunt.config('branch_src', branch_src);
			grunt.config('branch_dest', branch_dest);

			['uglify', 'cssmin', 'processCss'].map(function(task) {
				// 生成对应的配置段
				grunt.config(task + '.' + branch_src, grunt.config(task + '.vips'));
				grunt.task.run(task + ':' + branch_src);
			});
			// push branch-test, generate CHANGELOG
			grunt.task.run('push:' + branch_dest);

			branches.dev.push(branch_src);
			branches.test.push(branch_dest);
		}
		// 对应模板页面分支的处理
		for (tpl_src in tpl_branches) {
			tpl_dest = tpl_branches[tpl_src];
			grunt.task.run('push:' + tpl_src);

			branches.dev.push(tpl_src);
			branches.test.push(tpl_dest);
		}

		// 最后检查是否有遗漏的文件
		branches.test.map(function (branch) {
			grunt.task.run('st:' + branch);
		});

		// finish: 所有任务都结束后，用来输出一些结果信息
		grunt.task.run('finish:' + project.name);
	});

  /*
   * CSS变量替换
   */
  grunt.registerMultiTask('processCss', 'replace variables in CSS', function () {
    var options =  this.options({
      imgDomain: '',
      version: grunt.config('build')
    });
    var imgDomain = options.imgDomain,
        version = options.version;
    var dest = this.data;
		grunt.log.debug('Process to: ' + dest);
    var variablePattern = /\{\$.*?\}/;
    variablePattern.compile(variablePattern);
    function process(filename) {
        var css = grunt.file.read(filename)
          .replace(/\{\$imgDomain\}|\{\$staticImg\}/gm, imgDomain)
          .replace(/\{\$staticVer\}/gm, version.staticVer)
          .replace(/\{\$shopImgVer\}/gm, version.shopImgVer)
          .replace(/\{\$dayImgVer\}/gm, version.dayImgVer)
          .replace(/\{\$luxImgVer\}/gm, version.luxImgVer)
          .replace(/\{\$tourImgVer\}/gm, version.tourImgVer)
          .replace(/\{\$goodsImgVer\}/gm, version.goodsImgVer)
          .replace(/\{\$mallImgVer\}/gm, version.mallImgVer)
          .replace(/\{\$cardImgVer\}/gm, version.cardImgVer);
          //.replace(/\{\$.*?Ver\}/gm, version);

        // check if all variables are replaced
        if (variablePattern.test(css)) {
          grunt.warn('File ' + filename +
            '\nVariables does not be replaced all:' + css.match(variablePattern));
        }
        grunt.file.write(filename, css);
        grunt.log.writeln('Replace ' + filename + ' Successful');
    }
    if (grunt.file.isDir(dest)) {
      grunt.file.recurse(dest, process);
    }
    else if (grunt.file.isFile(dest)) {
      process(dest);
    }
  });

	// push task: svn commit，生成Changelog文件
	grunt.registerTask('push', function(branch) {
		var project = grunt.config('_project');
		if (!project) {
			grunt.log.warn('没有指定项目，默认项目名设置为default');
			project = {name: 'default'};
		}
		if (!branch) {
			grunt.fatal('没有指定要提交的分支');
		}
		// 配置changelog
		ChangeLog.project = project;
		ChangeLog.branch = branch;
		grunt.config('branch_dest', branch);
		grunt.task.run(['shell:update', 'shell:push']);
	});

	// 检查遗漏文件: svn st
	grunt.registerTask('st', function (branch) {
			grunt.config('branch_dest', branch);
			grunt.task.run('shell:st');
	});

	// finish: 所有任务都结束后，用来输出一些结果信息
	grunt.registerTask('finish', function (projectName) {
		var changelog = projectName + '-CHANGELOG';
		grunt.log.ok('CHANGELOG Generated, See: ' + changelog);
		grunt.log.writeln(grunt.file.read(changelog));

		var st_data = grunt.config('st_data');
		if (st_data && st_data.msg.length > 0) {
			grunt.log.warn('◉︵◉ 你可能还遗漏了这些文件:');
			grunt.log.writeln(st_data.msg);
		}
	});

	var ChangeLog = {
		project: {},
		branch: '',
		/*
		 * 自动生成更改文件列表: changelog
		 * project: GruntFile里面配置的项目名称
		 * revData: svn 提交返回的信息
		 */
		generate: function (revData, err) {
			var branch = this.branch || grunt.option('branch'),
					project = this.project;
			grunt.log.debug('Begin generate change log for: ' + project.name);
			if (err) {
				grunt.fatal(err);
			}
			if (!branch) {
				grunt.fatal('需要指定提交的branch');
			}
			var changelog = project.name + '-CHANGELOG',
					filepath = '',
					json = {};
			grunt.log.debug('Branch: ' + branch);
			if (grunt.file.exists(changelog)) {
				grunt.log.debug('File: ' + changelog + ' exists');
				json = grunt.file.readJSON(changelog);
			}
			else {
				// 关于项目的说明，可以配置在<%= project.description %>
				json['description'] = project.description || '';
			}
			var lines = revData.trim().split(/\r|\r\n|\n/),
					rev = 'r' + lines[lines.length - 1].match(/\d+/),
					filePattern = /\s.*\/.*\..+/;
			grunt.log.debug('lines: ' + lines);
			grunt.log.debug('last line: ' + lines[lines.length - 1]);
			grunt.log.debug('rev: ' + rev);
			filePattern.compile(filePattern);
			lines.map(function (line) {
				var match = line.match(filePattern);
				if (match) {
					grunt.log.debug('file matches: ' + match);
					filepath = match[0].replace(branch + '/', '').trim();
					json[branch] = json[branch] || {};
					json[branch][filepath] = rev;
				}
			});
			grunt.file.write(changelog, JSON.stringify(json, null, 4));
			//grunt.log.writeln('Changelog generated: ' + changelog);
		}
	};

  // for debug
  grunt.registerTask('debug', function(project) {
    //console.log('msg: ' + grunt.option('m'));
		//grunt.file.write('changelog', JSON.stringify(json, ' ', 4));
		//grunt.log.writeln('Write to File changelog');
		//console.log(grunt.config('processCss').options.imgDomain);
  });
};
